package com.dbw.pdftool;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.pdfbox.text.TextPosition;

/**
 * PDF文字提取器。
 * <p>
 * 可从PDF文件中，提取出一行行的文字。
 * 
 * @author dongb
 *
 */
public class PDFTextExtractor {

	/**
	 * PDF行数据。
	 * @author dongb
	 *
	 */
	public static class PDFLine {
		
		/**
		 * 本行文字
		 */
		private String text = null;
		
		/**
		 * 行首字符的  {@link org.apache.pdfbox.text.TextPosition TextPosition}
		 */
		private TextPosition headPosition = null;
		
		/**
		 * 本行所在的页数
		 */
		private int pageNo = 0;
		
		//TODO 行的位置、边界
		
		public void setText(String text) {
			this.text = text;
		}
		
		public String getText() {
			return text;
		}
		
		public void setHeadPosition(TextPosition headPosition) {
			this.headPosition = headPosition;
		}
		
		public TextPosition getHeadPosition() {
			return headPosition;
		}
		
		public void setPageNo(int pageNo) {
			this.pageNo = pageNo;
		}
		
		public int getPageNo() {
			return pageNo;
		}
	}
	
	/**
	 * 待解析的PDF文件
	 */
	private File pdfFile = null;
	
	/**
	 * 存放从文件提取的行列表
	 */
	private ArrayList<PDFLine> lineList = new ArrayList<PDFLine>();
	
	/**
	 * 使用PDF文件构造提取器
	 * @param pdfFile	待提取的PDF文件
	 */
	public PDFTextExtractor(File pdfFile) {
		this.pdfFile = pdfFile;
	}
	
	/**
	 * 提取文本信息
	 * 
	 * @throws Exception
	 */
	public void extract() throws Exception {
		PDDocument document = null;
		try {
			document = PDDocument.load(pdfFile);

			MyPDFTextStrippter stripper = new MyPDFTextStrippter();
			stripper.setSortByPosition(true);
			stripper.setStartPage(0);
			stripper.setEndPage(document.getNumberOfPages());

			Writer dummy = new OutputStreamWriter(new ByteArrayOutputStream());
			stripper.writeText(document, dummy);
			stripper.flush();

		} finally {
			if (document != null) {
				document.close();
			}
		}
	}
	
	/**
	 * PDF文本截取器。
	 * 
	 * @author dongb
	 *
	 */
	private class MyPDFTextStrippter extends PDFTextStripper {

		private TextPosition lineHeadTextPosition = null;
		
		private StringBuffer lineBuffer = new StringBuffer();
		
		private int linePageNo = 0;
		
		public MyPDFTextStrippter() throws IOException {
			super();
		}
		
		/**
	     * Override the default functionality of PDFTextStripper.
	     */
	    @Override
	    protected void writeString(String text, List<TextPosition> textPositions) throws IOException {
	        TextPosition textPosition = textPositions.get(0);
	        if(lineHeadTextPosition == null) {
	        	resetBuffer(textPosition);
	        	addToBuffer(text);
	        	return;
	        }
	        
	        if(textPosition.getYDirAdj() != lineHeadTextPosition.getYDirAdj()) {
	        	if(textPosition.getHeightDir() != lineHeadTextPosition.getHeightDir()) {
	        		addLine();
	        		resetBuffer(textPosition);
		        	addToBuffer(text);
	            	return;
	        	}
	        }
	        
	        addToBuffer(text);
	    }
	    
	    /**
	     * 强制刷新缓存，以结束最后一行数据的处理。
	     */
	    public void flush() {
	    	if(lineBuffer.length() != 0) {
	    		addLine();
	    	}
	    }
	    
	    /**
	     * 将当前缓存的行添加到{@link com.dbw.pdftool.PDFTextExtractor#lineList lineList}中
	     */
	    private void addLine() {
	    	PDFLine line = new PDFLine();
	    	line.setHeadPosition(lineHeadTextPosition);
	    	line.setText(lineBuffer.toString());
	    	line.setPageNo(linePageNo);
	    	lineList.add(line);
	    }
	    
	    private void resetBuffer(TextPosition headPosition) {
	    	lineHeadTextPosition = headPosition;
	    	lineBuffer = new StringBuffer();
	    	linePageNo = getCurrentPageNo();
	    }
	    
	    private void addToBuffer(String text) {
	    	lineBuffer.append(text);
        	lineBuffer.append(" ");
	    }
	}
	
	/**
	 * 获取存放从文件提取的行列表
	 * 
	 * @return
	 */
	public ArrayList<PDFLine> getLineList() {
		return lineList;
	}
}
